package com.urbanflow.vinci.controler;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.urbanflow.vinci.main.Arret;
import com.urbanflow.vinci.main.Horaire;
import com.urbanflow.vinci.parcourt.Branche;
import com.urbanflow.vinci.parcourt.Chemin;
import com.urbanflow.vinci.parcourt.Graphe;
import com.urbanflow.vinci.util.ComparatorChemin;

public class ParcoursManager {
	private static ParcoursManager singleton = new ParcoursManager();
	private Arret unArret;
	private Map<Integer,Arret> ensembleDesArrets= new HashMap<Integer,Arret>();
	private List<Graphe> mesReseaux = new ArrayList<Graphe>();
	private Map<Arret,Graphe> mesCorrespondances= new HashMap<Arret,Graphe>();
	private Branche maBranche;
	private Branche maBrancheEnCours;
	private Chemin leCheminPrevu;
	
	public static ParcoursManager getInstance(){
		return singleton;
	}
	
	public void creerReseau(List<Arret> desArret){
		List<Arret> lesArretParcouru = new ArrayList<Arret>();
		//if(! desArret.isEmpty()) { 
			Arret depart = desArret.get(0);
			//desArret.remove(depart);
			Graphe maBranche = new Graphe(depart);
			lesArretParcouru = maBranche.construireRecursif(desArret, new HashMap<Integer,Graphe>());
			desArret.removeAll(lesArretParcouru);
			mesReseaux.add(maBranche);
			
		List<Arret> arretAParcourir = new ArrayList<Arret>();
		arretAParcourir.add(depart);
	}
	
	public void creerLesTrajets(Arret debut, Arret fin, Date dateDepart) throws CheminNotFound {
		Graphe depart = debut.getPoint();
		if(depart == null) {
			throw new CheminNotFound();
		}		 
//		maBranche = depart.construireArbre(fin,null);
//		maBranche.supprimerSuperflue();
		
	//	System.out.println(maBranche.toString());
		List<Chemin> mesCheminsAVerifier = new ArrayList<Chemin>();
		Map<String,Chemin> mesCheminsVerifier = new HashMap<String,Chemin>();
		Chemin cheminEnCours = null;
		mesCheminsAVerifier.addAll(depart.getAllChemin(dateDepart, null));
		Collections.sort(mesCheminsAVerifier, new ComparatorChemin() );		
		while(!mesCheminsAVerifier.isEmpty()) {
			Iterator<Chemin>unIt = mesCheminsAVerifier.iterator();
			cheminEnCours = unIt.next();
			unIt.remove();
			if(cheminEnCours.getArrive() == fin) {
				leCheminPrevu = cheminEnCours;
				break;
			}			
			Chemin cheminVerifie = mesCheminsVerifier.get(cheminEnCours.getId());
			if(cheminVerifie == null || cheminVerifie.estPlusLourd(cheminEnCours)) {
				List<Chemin> lesChemins = cheminEnCours.retournerCheminSuivant();
				Iterator<Chemin> unItChemin = lesChemins.iterator();
				while(unItChemin.hasNext()) {
					Chemin enCours = unItChemin.next();
					cheminVerifie = mesCheminsVerifier.get(enCours.getId());
					if(cheminVerifie != null && cheminVerifie.estPlusLeger(cheminEnCours)) {
						unItChemin.remove();
					}
				}
				mesCheminsVerifier.put(cheminEnCours.getId(),cheminEnCours);
				mesCheminsAVerifier.addAll(lesChemins);
				Collections.sort(mesCheminsAVerifier, new ComparatorChemin());
			}
		}
	}
	
	public void reduireLeChemin(){
		if(leCheminPrevu != null) {
			leCheminPrevu = leCheminPrevu.congestionner();
		}
	}
	
	public List<Horaire> parcoursPrevu(Arret debut, Arret fin,Dictionary<Integer,Integer> monDico) {
		List<Arret> mesArretConnexe = ArretManager.getInstance().donnerlesArretsSuivant(debut);
		//monDico at: debut.getId() put: debut.getId();
		if(mesArretConnexe.contains(fin)) {
			//return HoraireManager.getInstance()
		}
		
		return null;
	}
	public ParcoursManager getSingleton() {
		return singleton;
	}

	public void setSingleton(ParcoursManager singleton) {
		this.singleton = singleton;
	}
	public Arret getUnArret() {
		return unArret;
	}
	public void setUnArret(Arret unArret) {
		this.unArret = unArret;
	}

	public Map<Integer,Arret> getEnsembleDesArrets() {
		return ensembleDesArrets;
	}

	public void setEnsembleDesArrets(Map<Integer,Arret> ensembleDesArrets) {
		this.ensembleDesArrets = ensembleDesArrets;
	}

	public Chemin getLeCheminPrevu() {
		return leCheminPrevu;
	}

	public void setLeCheminPrevu(Chemin leCheminPrevu) {
		this.leCheminPrevu = leCheminPrevu;
	}
	
	

}
